home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
oper_sys
/
emerald
/
emrldsys.lha
/
Language
/
Compiler
/
genexp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-08-16
|
14KB
|
514 lines
/*
* @(#)genexp.c 1.7 2/23/90
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include "assert.h"
#include "addresses.h"
#include "nodes.h"
#include "map.h"
#include "sequence.h"
#include "system.h"
#include "semantics.h"
#include "builtins.h"
#include "evaluate.h"
#include "opNames.h"
#include "primitives.h"
#include "allocate.h"
#include "MyParser.h"
#include "datadesc.h"
#include "environment.h"
#include "regdefs.h"
#include "genutils.h"
#include "emit.h"
#include "error.h"
#include "consts.h"
#include "flags.h"
#include "trace.h"
#include "option.h"
/*
* Imported routines
*/
extern void moveDataToRegister(), moveVariableToRegisters(), claimReg();
extern void resolveGlobal();
extern void findTemp();
extern DD generateCreation();
extern Boolean isARealImport();
extern NodePtr newExecuteAsAT(), tryToExecuteAsAT();
extern void generateInvocation();
extern NodePtr buildOpName();
/*
* Global variables
*/
extern int cEM_locates;
/*
* Exported definitions
*/
/*
* Local definitions
*/
/*
* Forward definitions
*/
void generateExpression(), generateExp(), generateUnaryExp();
void generate(), generateVectorLiteral();
void generateExpression(p, c)
NodePtr p;
Context c;
{
Variable result, *v;
register Symbol st;
NodePtr setqs, q, r;
Symbol sym;
assert((int)p >= 0x200);
result.data = nullDD;
result.abCon = nullDD;
switch (p->tag) {
case P_ARG:
/* ignore p->b.arg.move */
generateExpression(p->b.arg.exp, c);
break;
case P_SYMDEF:
case P_SYMREF:
st = ST_Fetch(p->b.symref.symbol);
vPushSymbol(st, c);
break;
case P_BUILTINLIT:
case P_NILLIT:
case P_BOOLLIT:
case P_INTLIT:
case P_STRINGLIT:
case P_CHARLIT:
case P_REALLIT:
vPushValue(p, c);
break;
case P_GLOBALREF:
resolveGlobal(p, (ValuePtr) NULL);
generateExpression(p->b.globalref.value, c);
break;
case P_ATLIT:
generate(p);
vPushValue(p, c);
break;
case P_OBLIT:
generate(p);
result.abCon = buildAbConFromObject(p);
if (p == currentObject) {
result.data.kind = DD_Self;
} else if (p->b.oblit.f.writeSeparately) {
/*
* This is an object that the compiler created, so the value of this
* expression is just a reference to the object.
*/
result.data.kind = DD_OIDToODP;
result.data.value.id = p->b.oblit.id;
} else if (p->b.oblit.f.isTypeVariable ||
p->b.oblit.f.dependsOnTypeVariable) {
ErrorMessage(p,
"This object depends on a type parameter and cannot be created");
} else {
/*
* This is needs to be translated into a call of the kernel.create
* primitive to actually build a new object.
*/
/*
* Allocate the space on the stack for the result.
*/
IFOPTION(createonstack, 1 &&
p->b.oblit.codeOID != OIDOfBuiltin(B_INSTCT, STRINGINDEX)) {
emitMove(result.abCon, pusher, 'l');
emitMove(nilDD, pusher, 'l');
}
/*
* Prepare the parameters to the initially of the object.
*/
setqs = p->b.oblit.setq;
Sequence_For(q, setqs)
/*
* Charge through the setq list and find the non-manifest ones and
* push their values on the stack.
*/
assert(q->tag == P_SETQ);
r = q->b.setq.inner;
assert(r->tag == P_SYMDEF);
sym = ST_Fetch(r->b.symdef.symbol);
if (isARealImport(sym, TRUE)) {
/*
* This is a real import. We need to push the current value of
* outer on the stack.
*/
r = q->b.setq.outer;
vPush(pusherContext.v);
generateExpression(r, pusherContext);
vGenerateAssign();
}
Sequence_Next
result.data = generateCreation(p, FALSE,
(Boolean)(OPTION(locals,1) && p->b.oblit.f.doLocalCreate));
}
vPush(result);
break;
case P_INVOC:
generateInvocation(p, 1, c);
break;
case P_EXP:
generateExp(p, c);
break;
case P_UNARYEXP:
generateUnaryExp(p, c);
break;
case P_VECTORLIT:
generateVectorLiteral(p);
break;
case P_VIEW:
generateExpression(p->b.view.exp, anyContext);
if (p->b.view.isRedundant) {
IFOPTION(comment, 1) Comment("\t\t\t\tRedundant view expression");
} else {
v = vPeek(0);
q = newExecuteAsAT(p->b.view.type);
assert(q->tag == P_ATLIT);
moveVariableToRegisters(v, regs_arg1);
IFOPTION(view, 1) {
result.data = buildManifestDD((int)q->b.atlit.id);
ensureGenerate(q->b.atlit.id);
result.abCon = buildConCon(INTEGERINDEX);
moveDataToRegister(&result, regs_arg3, DataBrand);
preemptReg(regs_scratch, 1);
generateKernelCall("em_tryview");
} else IFOPTION(view, 2) {
result.data.kind = DD_OIDToCodePtr;
result.data.value.id = q->b.atlit.id;
ensureGenerate(q->b.atlit.id);
result.abCon = buildConCon(SIGNATUREINDEX);
moveDataToRegister(&result, regs_arg3, ODPBrand);
preemptReg(regs_scratch, 1);
generateKernelCall("em_tryviewptr");
} else {
assert(FALSE);
}
vDiscard();
freeReg(regs_arg3, 1);
claimReg(regs_arg1, 2, VariableBrand);
result.data = buildRegisterDD(regs_arg1);
result.abCon = nextAddress(result.data);
setDDAbstractType(result.abCon, q->b.atlit.id);
vPush(result);
}
break;
case P_RESTRICT:
generateExpression(p->b.restrict.exp, anyContext);
v = vPeek(0);
q = newExecuteAsAT(p->b.restrict.type);
assert(q->tag == P_ATLIT);
moveVariableToRegisters(v, regs_arg1);
result.data.kind = DD_OIDToCodePtr;
result.data.value.id = q->b.atlit.id;
ensureGenerate(q->b.atlit.id);
result.abCon = buildConCon(SIGNATUREINDEX);
moveDataToRegister(&result, regs_arg3, ODPBrand);
preemptReg(regs_scratch, 1);
generateKernelCall("em_restrictptr");
vDiscard();
freeReg(regs_arg3, 1);
claimReg(regs_arg1, 2, VariableBrand);
result.data = buildRegisterDD(regs_arg1);
result.abCon = nextAddress(result.data);
setDDAbstractType(result.abCon, q->b.atlit.id);
vPush(result);
break;
default:
ErrorMessage(p, "Garbage in generateExpression");
assert(FALSE);
vPush(result);
break;
}
}
Boolean allAreManifest(p)
register NodePtr p;
{
register NodePtr q;
Sequence_For(q, p->b.vectorlit.exp)
if (!isATrivialLiteral(q)) return(FALSE);
if (q->tag == P_STRINGLIT) return(FALSE);
Sequence_Next
return(TRUE);
}
void generateVectorLiteral(p)
NodePtr p;
{
NodePtr vt, q, instct;
Symbol elementTypeSymbol;
int elementTypeSize;
Variable etsv, *ets = &etsv, ctv, *ct = &ctv, result, nev, *ne = &nev;
assert(p->tag == P_VECTORLIT);
vt = p->b.vectorlit.vectorType;
assert(vt != NN);
vt = GETVALUE(vt);
assert(vt->tag == P_OBLIT);
assert(vt->b.oblit.f.writeSeparately);
assert(vt->b.oblit.f.isManifest);
assert(vt->b.oblit.id != 0);
ensureGenerate(vt->b.oblit.id);
instct = findInstCode(vt);
assert(instct != NULL);
assert(instct->tag == P_OBLIT);
ct->data.kind = DD_OIDToCodePtr;
ct->data.value.id = getCodeOID(instct);
ct->abCon = buildAbConFromObject(instct);
elementTypeSymbol = getElementTypeSymbol(instct);
elementTypeSize = getSymbolSize(elementTypeSymbol);
if (allAreManifest(p)) {
if (!doGenerateCode)
TRACE1(generate, 1, "A manifest vectorliteral on line %d",
p->lineNumber);
result.data.kind = DD_Label;
result.data.value.label = nextLabelNumber++;
result.abCon = ct->abCon;
squirrelVectorLiteral(result.data.value.label, p, elementTypeSize,
getCodeOID(instct));
vPush(result);
return;
}
TS_StartInvocation();
IFOPTION(createonstack, 1) {
emitMove(ct->abCon, pusher, 'l');
emitMove(nilDD, pusher, 'l');
}
Sequence_For(q, p->b.vectorlit.exp)
vPush(pusherContext.v);
generateExpression(q, pusherContext);
vGenerateAssign();
TS_Push();
Sequence_Next
TS_EndInvocation();
ne->data = buildManifestDD(Sequence_Length(p->b.vectorlit.exp));
ne->abCon = buildConCon(INTEGERINDEX);
moveDataToRegister(ne, regs_arg3, DataBrand);
ets->data = buildManifestDD(elementTypeSize);
ets->abCon = buildConCon(INTEGERINDEX);
moveDataToRegister(ets, regs_arg2, DataBrand);
result.abCon = ct->abCon;
moveDataToRegister(ct, regs_arg1, ODPBrand);
preemptReg(regs_scratch, 1);
#ifdef MUTABLEVECTORLITERALS
if (OPTION(locals, 1) && p->b.vectorlit.f.doLocalCreate) {
generateKernelCall("em_localCreateVectorLiteral");
} else {
generateKernelCall("em_globalCreateVectorLiteral");
}
#else
generateKernelCall("em_localCreateVectorLiteral");
#endif
FREEV(ets);
FREEV(ct);
FREEV(ne);
claimReg(regs_arg1, 1, ODPBrand);
result.data = buildRegisterDD(regs_arg1);
IFOPTION(createonstack, 1) {
emitMove(popper, result.data, 'l');
emit(POPABCON);
}
vPush(result);
}
/*ARGSUSED*/
void generateExp(p, c)
NodePtr p;
Context c;
{
Variable resultV, *result = &resultV, *left, *right, answer, rightV, leftV;
Variable temp;
NodePtr q, r, eleft;
int truelabel, falselabel, endlabel;
result->data = nullDD;
result->abCon = nullDD;
assert(p->tag == P_EXP);
switch (p->b.exp.op) {
case KOR:
findTemp(result, 4, DataBrand);
result->abCon = buildConCon(BOOLEANINDEX);
vPush(*result);
result = vPeek(0);
truelabel = nextLabelNumber++;
falselabel = nextLabelNumber++;
endlabel = nextLabelNumber++;
generateExpression(p->b.exp.left, pslContext);
generateBranch(TRUE, truelabel);
generateExpression(p->b.exp.right, pslContext);
generateBranch(TRUE, truelabel);
answer.data = buildManifestDD(0);
answer.abCon = buildConCon(BOOLEANINDEX);
ddGenerateAssign(result->data, result->abCon, answer.data, answer.abCon);
emit("\tj%s\tL_%d\n", JN(ALWAYS), endlabel);
emit("L_%d:\n", truelabel);
answer.data = buildManifestDD(1);
answer.abCon = buildConCon(BOOLEANINDEX);
ddGenerateAssign(result->data, result->abCon, answer.data, answer.abCon);
emit("L_%d:\n", endlabel);
break;
case KAND:
findTemp(result, 4, DataBrand);
vPush(*result);
result = vPeek(0);
result->abCon = buildConCon(BOOLEANINDEX);
truelabel = nextLabelNumber++;
falselabel = nextLabelNumber++;
endlabel = nextLabelNumber++;
generateExpression(p->b.exp.left, pslContext);
generateBranch(FALSE, falselabel);
generateExpression(p->b.exp.right, pslContext);
generateBranch(FALSE, falselabel);
answer.data = buildManifestDD(1);
answer.abCon = buildConCon(BOOLEANINDEX);
ddGenerateAssign(result->data, result->abCon, answer.data, answer.abCon);
emit("\tj%s\tL_%d\n", JN(ALWAYS), endlabel);
emit("L_%d:\n", falselabel);
answer.data = buildManifestDD(0);
answer.abCon = buildConCon(BOOLEANINDEX);
ddGenerateAssign(result->data, result->abCon, answer.data, answer.abCon);
emit("L_%d:\n", endlabel);
break;
case OIDENTITY:
case ONOTIDENTITY:
result->abCon = buildConCon(BOOLEANINDEX);
generateExpression(p->b.exp.left, anyContext);
left = vPeek(0);
vForceToTemp(left, TS_All);
generateExpression(p->b.exp.right, anyContext);
right = vPeek(0);
vForceToTemp(right, TS_All);
currentInstruction = nextLabelNumber++;
result->data =
generateCompare(left, right, 'l', p->b.exp.op == OIDENTITY ? EQL : NEQ);
vDiscard();
vDiscard();
vPush(*result);
break;
case OCONFORMSTO:
/* Try to execute the left operand as an AT. */
r = tryToExecuteAsAT(p->b.exp.left);
if (r == NULL) {
eleft = p->b.exp.left;
if (! conforms(evaluateForAT(eleft, TRUE),
refToBuiltin(B_INSTAT, SIGNATUREINDEX))) {
eleft = Construct(P_INVOC, 3,
eleft,
buildOpName("getsignature", -1),
NN);
}
generateExpression(eleft, anyContext);
left = vPeek(0);
moveDataToRegister(left, regs_arg1, DataBrand);
emitMove(buildAddressDD(regs_arg1, /* Code_ownOID */ 4), buildRegisterDDNC(regs_arg1), 'l');
} else {
assert(r->tag == P_ATLIT);
assert(r->b.atlit.id != 0);
left = &leftV;
left->abCon = buildConCon(INTEGERINDEX);
left->data = buildManifestDD((int)r->b.atlit.id);
ensureGenerate(r->b.atlit.id);
moveDataToRegister(left, regs_arg1, DataBrand);
}
q = newExecuteAsAT(p->b.exp.right);
assert(q != NULL);
assert(q->tag == P_ATLIT);
assert(q->b.atlit.id != 0);
right = &rightV;
right->abCon = buildConCon(INTEGERINDEX);
right->data = buildManifestDD((int)q->b.atlit.id);
ensureGenerate(q->b.atlit.id);
moveDataToRegister(right, regs_arg2, DataBrand);
preemptReg(regs_scratch, 1);
preemptReg(regs_arg3, 1);
generateKernelCall("em_conform");
FREEV(left);
FREEV(right);
claimReg(regs_arg1, 1, DataBrand);
result->abCon = buildConCon(BOOLEANINDEX);
result->data = buildRegisterDD(regs_arg1);
if (r == NULL) {
vDiscard();
}
vPush(*result);
break;
default:
assert(FALSE);
break;
}
}
/*ARGSUSED*/
void generateUnaryExp(p, c)
NodePtr p;
Context c;
{
Variable result;
assert(p->tag == P_UNARYEXP);
switch (p->b.unaryexp.op) {
case KAWAITING:
generateExpression(p->b.unaryexp.exp, anyContext);
moveDataToRegister(vPeek(0), regs_arg1, ODPBrand);
preemptReg(regs_scratch, 1);
preemptReg(regs_arg2, 2);
generateKernelCall("em_condAwaiting");
vDiscard();
claimReg(regs_arg1, 1, DataBrand);
result.data = buildRegisterDD(regs_arg1);
result.abCon = buildConCon(BOOLEANINDEX);
break;
case KISFIXED:
generateExpression(p->b.unaryexp.exp, anyContext);
moveVariableToRegisters(vPeek(0), regs_arg1);
preemptReg(regs_scratch, 1);
preemptReg(regs_arg3, 1);
generateKernelCall("em_isFixed");
vDiscard();
claimReg(regs_arg1, 1, DataBrand);
result.data = buildRegisterDD(regs_arg1);
result.abCon = buildConCon(BOOLEANINDEX);
break;
case KLOCATE:
generateExpression(p->b.unaryexp.exp, anyContext);
moveVariableToRegisters(vPeek(0), regs_arg1);
preemptReg(regs_scratch, 1);
preemptReg(regs_arg3, 1);
INC(cEM_locates);
generateKernelCall("em_locate");
vDiscard();
claimReg(regs_arg1, 1, ODPBrand);
result.data = buildRegisterDD(regs_arg1);
result.abCon = buildConCon(NODEINDEX);
break;
default:
assert(FALSE);
break;
}
vPush(result);
}